\NeedsTeXFormat{LaTeX2e}
\RequirePackage{listings,verbatim}
\ProvidesPackage{stys/codeblock}
\usepackage{fontspec}
\usepackage{lstfiracode}
\setmonofont{FiraCode-Regular.ttf}[
    BoldFont=FiraCode-Bold.ttf,
    Contextuals=Alternate  % Activate the calt feature
]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% code listings
%% 代码块设定
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% 定义代码块颜色
\definecolor{codecolorkeywords}{rgb}{0,0,1}
\definecolor{codecolorcomments}{rgb}{0,0.5,0}
\definecolor{codecolorxmlcomments}{rgb}{0.5,0.5,0.5}
\definecolor{codecolorstrings}{rgb}{0.64,0.08,0.08}
\definecolor{codecolortypes}{rgb}{0.17,0.57,0.68}
\definecolor{codecolorbg}{rgb}{0.92,0.92,0.92}
% 定义各类语言
% region lang
\lstdefinelanguage{Python}{
    keywords={False, None, True, and, as, assert, async, await, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield},
    sensitive=true,
    comment=[l]{\#},
    morecomment=[s]{"""}{"""},
    morecomment=[s]{'''}{'''},
    morestring=[b]',
    morestring=[b]"
}

\lstdefinelanguage{C++}{
    keywords={alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char8_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, override, private, protected, public, register, reinterpret_cast, requires, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    string=[b]{"}
}

\lstdefinelanguage{C}{
    keywords={auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, inline, int, long, register, restrict, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while, _Alignas, _Alignof, _Atomic, _Generic, _Imaginary, _Noreturn, _Static_assert, _Thread_local},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    string=[b]{"}
}

\lstdefinelanguage{CSharp}{
    keywords={abstract, as, base, bool, break, byte, case, catch, char, checked, class, const, continue, decimal, default, delegate, do, double, else, enum, event, explicit, extern, false, finally, fixed, float, for, foreach, goto, if, implicit, in, int, interface, internal, is, lock, long, namespace, new, null, object, operator, out, override, params, private, protected, public, readonly, ref, return, sbyte, sealed, short, sizeof, stackalloc, static, string, struct, switch, this, throw, true, try, typeof, uint, ulong, unchecked, unsafe, ushort, using, virtual, void, volatile, while},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    string=[b]{"}
}
\lstdefinelanguage{LaTeX}{
    keywords={documentclass, usepackage, begin, end, chapter, section, subsection, subsubsection, paragraph, subparagraph, title, author, date, maketitle, tableofcontents, include, input, bibliography, cite, newcommand, renewcommand, textbf, textit, textsl, texttt, emph, itemize, enumerate, description, figure, caption, label, ref, pageref, footnote, marginpar, verbatim},
    sensitive=true,
    comment=[l]{\%},
    string=[b]{"}
}
\lstdefinelanguage{Pascal}{
    keywords={and, array, begin, case, const, continue, destructor, div, do, downto, else, end, file, for, function, goto, if, implementation, in, inline, interface, label, mod, nil, not, object, of, or, packed, procedure, program, record, repeat, set, then, to, type, unit, until, var, while, with, write, writeln},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{(*}{*)},
    string=[b]{"}
}
\lstdefinelanguage{Fortran}{
    keywords={program, end, implicit, none, integer, real, double, complex, character, logical, if, then, else, do, while, select, case, stop, call, subroutine, function, return, module, contains, use, data, equivalence, dimension, parameter, allocate, deallocate, intrinsic, external, write, read, open, close, format, print},
    sensitive=true,
    comment=[l]{!},
    string=[b]{"}
}
\lstdefinelanguage{Bash}{
    keywords={if, then, else, elif, fi, for, in, do, done, while, until, case, esac, function, return, select, break, continue, export, readonly, local, unset, source, alias, grep, awk, sed, echo, printf, test, let, expr},
    sensitive=true,
    comment=[l]{\#},
    string=[b]{"},
}
\lstdefinelanguage{LAMMPS}{
    keywords={units, atom_style, boundary, read_data, read_restart, write_data, fix, compute, pair_style, pair_coeff, group, timestep, run, minimize, variable, if, else, endif, label, jump, include, run_style, thermo, thermo_style, dump, restart, velocity, mass, set, delete_atoms, create_atoms, region, lattice, create_box, fix_modify, neigh_modify},
    sensitive=true,
    comment=[l]{\#},
    string=[b]{"},
}
\lstdefinelanguage{XML}{
    keywords={<?xml, <, >, </, />, !DOCTYPE, !ELEMENT, !ATTLIST, !ENTITY, <!\[CDATA\[, \]\]>},
    sensitive=true,
    comment=[l]{<!--},
    morecomment=[s]{<!--}{-->},
    string=[b]{"},
}
\lstdefinelanguage{CSS}{
    keywords={@import, @media, @font-face, @keyframes, @supports, color, background, margin, padding, border, width, height, display, position, float, clear, text-align, font-size, font-weight, line-height, opacity, z-index, overflow, transition, transform, animation, flex, grid},
    sensitive=true,
    comment=[l]{/*},
    morecomment=[s]{/*}{*/},
    string=[b]{"},
    morestring=[b]''
}
\lstdefinelanguage{HTML}{
    keywords={<!DOCTYPE, <html, <head, <title, <body, <h1, <h2, <h3, <h4, <h5, <h6, <p, <a, <div, <span, <img, <link, <script, <style, <ul, <ol, <li, <table, <tr, <td, <th, <form, <input, <button, <textarea, <select, <option, <br, <hr, </html, </head, </title, </body, </h1, </h2, </h3, </h4, </h5, </h6, </p, </a, </div, </span, </img, </link, </script, </style, </ul, </ol, </li, </table, </tr, </td, </th, </form, </input, </button, </textarea, </select, </option, </br, </hr},
    sensitive=true,
    comment=[l]{<!--},
    morecomment=[s]{<!--}{-->},
    string=[b]{"},
    morestring=[b]''
}

\lstdefinelanguage{Matlab}{
    keywords={break, case, catch, classdef, continue, else, elseif, end, for, function, if, otherwise, parfor, persistent, return, spmd, switch, try, while, properties, methods, import, global, persistent, enum, true, false, NaN, inf},
    sensitive=true,
    comment=[l]{\%},
    morecomment=[s]{\%\{}{\%\}},
    morestring=[b]{'},
    morestring=[b]{"}
}

\lstdefinelanguage{JavaScript}{
    keywords={do, if, in, for, let, new, try, var, case, else, enum, eval, null, this, true, void, with, await, break, catch, class, const, false, super, throw, while, yield, delete, export, import, public, return, static, switch, typeof, default, extends, finally, package, private, continue, debugger, function, arguments, interface, protected, implements, instanceof},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    morestring=[b]',
    morestring=[b]"
}

\lstdefinelanguage{TypeScript}{
    keywords={abstract, break, case, catch, class, const, continue, debugger, default, delete, do, else, enum, export, extends, false, finally, for, function, if, import, in, instanceof, new, null, return, super, switch, this, throw, true, try, typeof, var, void, while, with, as, implements, interface, let, package, private, protected, public, static, yield, any, boolean, constructor, declare, get, module, require, number, set, string, symbol, type, from, of},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    morestring=[b]',
    morestring=[b]"
}

\lstdefinelanguage{golang}{
    keywords={break, default, func, interface, select, case, defer, go, map, struct, chan, else, goto, package, switch, const, fallthrough, if, range, type, continue, for, import, return, var},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    morestring=[b]',
    morestring=[b]"
}

% 伪代码
\lstdefinelanguage{psd}{
    keywords={if, then, else, endif, while, do, endwhile, for, endfor, return, function, input, output, declare, array, integer, float, string},
    sensitive=true,
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    string=[b]{"}
}
% endregion lang

\lstset{
    style=FiraCodeStyle,   % Use predefined FiraCodeStyle
    basicstyle=\ttfamily,   % Use \ttfamily for source code listings
    frame=tb,
    % framesep=5pt,
    framerule=.5pt,
    rulecolor=\color{violet},
    abovecaptionskip=0pt,
    belowcaptionskip=5pt,
    % Code design
    keywordstyle=\color{codecolorkeywords},
    commentstyle=\color{codecolorcomments},
    stringstyle=\color{codecolorstrings},
    numberstyle=\small\color{gray},
    breakatwhitespace=false,
    % breaklines=true,
    captionpos=t,
    keepspaces=true,
    % Line numbers
    numbers=left,
    numbersep=10pt,
    xleftmargin=.8em,
    stepnumber=1,
    firstnumber=1,
    numberfirstline=true,
    % Code
    tabsize=4,
    showspaces=false,
    showstringspaces=false,
    showtabs=false,
    breaklines=true,
    backgroundcolor=\color{codecolorbg}
}


\lstdefinestyle{shellstyle}{
    numbers=none
}


%% 代码列表标题
\RequirePackage{caption}
\DeclareCaptionFormat{codecaptionformat}{%
    %%\colorbox{black!20}{
    %%  \parbox{\textwidth}{#1#2\ttfamily#3}
    %%}
    \parbox{\textwidth}{\faCode #1#2\hspace{.5em}#3}
}
\captionsetup[lstlisting]{format=codecaptionformat}